package com.zxiw.zxedu.recyclerview.adapter

import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.annotation.IntDef
import androidx.recyclerview.widget.RecyclerView
import com.zxiw.zxedu.recyclerview.XRecyclerView


/**
 * @author zhangxiaoming
 * @date 2023/8/18
 * @description 提供便捷操作,可设置状态的错误页面、空页面、加载中页面、内容页面自由切换
 */
@SuppressLint("NotifyDataSetChanged")
abstract class HelperStateRecyclerViewAdapter<T>(context: Context, vararg layoutId: Int) :
    HelperRecyclerViewAdapter<T>(context, *layoutId) {
    @IntDef(STATE_NORMAL, STATE_LOADING, STATE_EMPTY, STATE_ERROR)
    @Retention(AnnotationRetention.SOURCE)
    annotation class State {}

    @State
    var state = STATE_NORMAL
        set(state) {
            field = state
            mRecyclerView?.let {
                when (state) {
                    STATE_LOADING, STATE_EMPTY, STATE_ERROR ->
                        it.setEnabledScroll(false)
                    STATE_NORMAL ->
                        it.setEnabledScroll(true)
                }
            }
            notifyDataSetChanged()
        }
    private var mRecyclerView: XRecyclerView? = null

    companion object {
        const val STATE_NORMAL = 0
        const val STATE_LOADING = 1
        const val STATE_EMPTY = 2
        const val STATE_ERROR = 3

        const val TYPE_LOADING = 1000
        const val TYPE_EMPTY = 1001
        const val TYPE_ERROR = 1002
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        if (recyclerView is XRecyclerView) {
            mRecyclerView = recyclerView
        }
        super.onAttachedToRecyclerView(recyclerView)
    }

    override fun getItemCount(): Int {
        when (state) {
            STATE_LOADING, STATE_EMPTY, STATE_ERROR -> return 1
        }
        return super.getItemCount()
    }

    override fun getItemViewType(position: Int): Int {
        when (state) {
            STATE_LOADING -> return TYPE_LOADING
            STATE_EMPTY -> return TYPE_EMPTY
            STATE_ERROR -> return TYPE_ERROR
        }
        return super.getItemViewType(position)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BH {
        when (viewType) {
            TYPE_LOADING -> return HelperRecyclerViewHolder(getLoadingView(parent), 0)
            TYPE_EMPTY -> return HelperRecyclerViewHolder(getEmptyView(parent), 0)
            TYPE_ERROR -> return HelperRecyclerViewHolder(getErrorView(parent), 0)
        }
        return super.onCreateViewHolder(parent, viewType)
    }

    override fun onBindViewHolder(viewHolder: BH, position: Int) {
        when (state) {
            STATE_LOADING -> onBindLoadingViewHolder(viewHolder as HelperRecyclerViewHolder)
            STATE_EMPTY -> onBindEmptyViewHolder(viewHolder as HelperRecyclerViewHolder)
            STATE_ERROR -> onBindErrorViewHolder(viewHolder as HelperRecyclerViewHolder)
            else -> super.onBindViewHolder(viewHolder, position)
        }
    }

    open fun onBindErrorViewHolder(holder: HelperRecyclerViewHolder) {}

    open fun onBindEmptyViewHolder(holder: HelperRecyclerViewHolder) {}

    open fun onBindLoadingViewHolder(holder: HelperRecyclerViewHolder) {}
    abstract fun getEmptyView(parent: ViewGroup): View

    abstract fun getErrorView(parent: ViewGroup): View

    abstract fun getLoadingView(parent: ViewGroup): View

    private fun invalidateState() {
        state = if (super.getItemCount() > 0) {
            STATE_NORMAL
        } else {
            STATE_EMPTY
        }
    }

    override fun addAll(startPosition: Int, datas: List<T>): Boolean {
        val b = super.addAll(startPosition, datas)
        invalidateState()
        return b
    }

    override fun addItemsToLast(datas: List<T>): Boolean {
        val b = super.addItemsToLast(datas)
        invalidateState()
        return b
    }

    override fun add(startPosition: Int, data: T) {
        super.add(startPosition, data)
        invalidateState()
        notifyDataSetChanged()
    }

    override fun alterObj(index: Int, data: T) {
        super.alterObj(index, data)
        invalidateState()
        notifyDataSetChanged()
    }


    override fun remove(data: T): Boolean {
        val b = super.remove(data)
        invalidateState()
        notifyDataSetChanged()
        return b
    }

    override fun removeToIndex(index: Int) {
        super.removeToIndex(index)
        invalidateState()
        notifyDataSetChanged()
    }


    override fun setListAll(datas: List<T>): Boolean {
        val result = super.setListAll(datas)
        invalidateState()
        notifyDataSetChanged()
        return result
    }

    override fun clear() {
        super.clear()
        invalidateState()
        notifyDataSetChanged()
    }
}